#include "TcpServer.h"
#include "ChooseInterface.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QNetworkInterface>
#include <QLabel>
#include <QColor>

TcpServer::TcpServer(QWidget *parent)
    : QWidget(parent)
{
    // 创建服务器
    _tcpServer = new QTcpServer(this);
    _ipTxt = new QLineEdit;
    _ipTxt->setText(QNetworkInterface().allAddresses().at(1).toString());

    _btnConnect = new QPushButton("连接");
    _btnConnect->setEnabled(true);
    _btnSend = new QPushButton("发送");
    _btnSend->setFixedHeight(60);
    _btnSend->setEnabled(false);

    QVBoxLayout* vMainLayout = new QVBoxLayout;
    QHBoxLayout* hLayout = new QHBoxLayout;     // 水平布局

    QVBoxLayout* vLayout1 = new QVBoxLayout;
    _show = new QTextBrowser;   // 显示
    _show->setFixedWidth(400);
    _show->setFixedHeight(400);
//    _show->setStyleSheet("background-color: green;");
    vLayout1->addWidget(_show);
    vLayout1->addStrut(1);

    QVBoxLayout* vLayout = new QVBoxLayout;     // 垂直布局
    QLabel* lblIP = new QLabel("本机IP地址");
    vLayout->addWidget(lblIP);
    vLayout->addWidget(_ipTxt);

    QLabel* lblPort = new QLabel("本地端口号");
    vLayout->addWidget(lblPort);

    _portTxt = new QLineEdit;           // 端口控件实例化
    vLayout->addWidget(_portTxt);
    vLayout->addWidget(_btnConnect);

    _btnClear = new QPushButton("清楚窗口");
    vLayout->addWidget(_btnClear);

    _cbxConnection = new QComboBox;     // 下拉框
    _cbxConnection->addItem("全部连接");
    vLayout->addWidget(_cbxConnection);

    vLayout->addStretch(1);

    hLayout->addLayout(vLayout1);
    hLayout->addLayout(vLayout);
    hLayout->addStrut(1);

    QHBoxLayout* hLayout1 = new QHBoxLayout;
    _sendTxt = new QTextEdit;   // 发送框
    _sendTxt->setFixedHeight(60);
    hLayout1->addWidget(_sendTxt);
    hLayout1->addWidget(_btnSend);

    vMainLayout->addLayout(hLayout);
    vMainLayout->addLayout(hLayout1);

    this->setLayout(vMainLayout);

    connect(_tcpServer, SIGNAL(newConnection()), this, SLOT(NewConnectionSlot()));
    connect(_btnConnect, SIGNAL(clicked()), this, SLOT(on_btnConnect_clicked()));
    connect(_btnSend, SIGNAL(clicked()), this, SLOT(on_btnSend_clicked()));
    connect(_btnClear, SIGNAL(clicked()), this, SLOT(on_btnClear_clicked()));
}

TcpServer::~TcpServer()
{
}

/**
 * 通过nextPendingConnection()获得连接过来的客户端信息，取到peerAddress和peerPort后显示在comboBox(cbxConnection)上，
 * 并将客户端的readyRead()信号连接到服务器端自定义的读数据槽函数ReadData()上。
 * 将客户端的disconnected()信号连接到服务器端自定义的槽函数disconnectedSlot()上。
 * @brief TcpServer::NewConnectionSlot
 */
void TcpServer::NewConnectionSlot()
{
    // 调用 nextPendingConnection 去获取socket连接
    _currentClient = _tcpServer->nextPendingConnection();
    _tcpClient.append(_currentClient); // 将新的客户端添加到集合
    _cbxConnection->addItem(tr("%1%2").arg(_currentClient->peerAddress().toString().split("::ffff")[1])
            .arg(_currentClient->peerPort()));
    connect(_currentClient, SIGNAL(readyRead()), this, SLOT(ReadData()));
//    connect(_currentClient, SIGNAL(disconnected()), this, SLOT(disconnectedSlot()));
}

/**
 * 客户端 断开连接
 * @brief TcpServer::disConnectedSlot
 */
void TcpServer::disConnectedSlot()
{
    foreach(QTcpSocket* socket, _tcpClient)
    {
        if(socket->state() == QAbstractSocket::UnconnectedState)
        {
            // 删除存储在combox中的客户端信息
            _cbxConnection->removeItem(_cbxConnection->findText(tr("%1:%2")
                                .arg(socket->peerAddress().toString().split("::ffff")[1])
                                .arg(socket->peerPort())));

            // 删除存储在_tcpClient列表中的客户端信息
            socket->destroyed();
            _tcpClient.removeOne(socket);   // 从客户端列表中移除
        }
    }
}

/**
 * 遍历tcpClient列表来读取数据
 * @brief TcpServer::ReadData
 */
void TcpServer::ReadData()
{
    // 由于readyRead信息并未提供SocketDecriptor, 所以需要遍历所有客户端
    foreach(QTcpSocket* socket, _tcpClient)
    {
        QByteArray buffer = socket->readAll();
        if(buffer.isEmpty()) continue;

        static QString IP_Port, IP_Port_pre;
        IP_Port = tr("[%1:%2]").arg(socket->peerAddress().toString().split("::ffff")[1]).arg(socket->peerPort());

        // 若此次信息的地址与上次不同，则需显示此次消息的客户端地址
        if(IP_Port != IP_Port_pre)
            _show->append(IP_Port);

        _show->append(buffer);

        // 更新ip_port
        IP_Port_pre = IP_Port;
    }
}

/**
 * 监听端口的函数
 * @brief TcpServer::on_btnConnect_clicked
 */
void TcpServer::on_btnConnect_clicked()
{
    if(_btnConnect->text() == tr("连接"))
    {
        bool ok = _tcpServer->listen(QHostAddress::Any, _portTxt->text().toUInt());
        if(ok) {
            _btnConnect->setText("断开");
            _btnSend->setEnabled(true);
        }
    }
    else
    {
        foreach(QTcpSocket *socket, _tcpClient)
        {
            socket->disconnectFromHost();// 断开连接
            bool ok = socket->waitForDisconnected(1000);
            if(!ok)
            {
                // 处理异常
            }
            _tcpClient.removeOne(socket);   // 从客户端列表中移除
        }
        _tcpServer->close();    // 不再监听端口
        _btnConnect->setText("连接");
        _btnSend->setEnabled(false);
    }
}

void TcpServer::on_btnSend_clicked()
{
    QString data = _sendTxt->toPlainText();
    // 全部连接
    if(_cbxConnection->currentIndex() == 0)
    {
        foreach(QTcpSocket* socket, _tcpClient)
            socket->write(data.toUtf8());
    }
    else
    {
        // 指定连接
        QString clientIP = _cbxConnection->currentText().split(":")[0];
        int clientPort = _cbxConnection->currentText().split(":")[1].toUInt();
        foreach(QTcpSocket* socket, _tcpClient)
        {
            if(socket->peerAddress().toString().split("::ffff:")[1]==clientIP && socket->peerPort()==clientPort)
            {
                socket->write(data.toUtf8());
                return;
            }
        }
    }
    _sendTxt->clear();
}

void TcpServer::on_btnClear_clicked()
{
    _show->clear();
}

